import { _decorator, Component, Node, Mask, v3, Vec3, tween, Label, SpriteFrame, UITransform, Tween, color, Sprite, clamp } from 'cc';
import { BasicUI } from '../../Init/Basic/BasicUI';
import { StorageSystem } from '../../Init/SystemStorage/StorageSystem';
import GlobalPool from '../../Init/Tools/GlobalPool';
const { ccclass, property } = _decorator;

@ccclass('MapUI')
export class MapUI extends BasicUI {
    curLv = 1;

    @property(Node)
    miniBg: Node = null;
    @property(Node)
    bigBg: Node = null;
    @property(Node)
    map: Node = null;
    @property(Node)
    title: Node = null;
    @property(Label)
    lvLabel: Label = null;
    @property(Mask)
    mask: Mask = null;
    @property(Node)
    effectLayer: Node = null;

    atkedColor = color().fromHEX('#518763');
    readyAtkColor = color().fromHEX('#cc5c5f');
    unatkColor = color().fromHEX('#e0e0e0');

    public show(d?) {
        this.node.active = true;
        this.onEvents();
        //关卡
        let _curLv = StorageSystem.getData().levelAssets.curLv;
        //test
        // _curLv = 40;
        this.lvLabel.string = _curLv.toFixed(0);
        //
        //显示地图颜色信息

        for (let i = 0; i < this.map.children.length; i++) {
            const e = this.map.children[i];
            let sp = e.getComponent(Sprite);
            if (i < _curLv - 1) {
                sp.color = this.atkedColor;
            } else {
                sp.color = this.unatkColor;
            }
        }

        let nextSp: Sprite = null;
        let nextIdx = 0;

        if (this.curLv < _curLv) {
            let mapItem: Node = this.map.children[_curLv - 2];
            if (!mapItem) {
                mapItem = this.map.children[this.map.children.length - 1];
            }
            let sp = mapItem.getComponent(Sprite);
            sp.color = this.unatkColor;
            //
            this.showBig(mapItem, () => {
                sp.color = this.atkedColor;
                //
                nextIdx = clamp(0, _curLv - 1, this.map.children.length - 1);
                nextSp = this.map.children[nextIdx].getComponent(Sprite);
                nextSp && (nextSp.color = this.readyAtkColor);
            });
        } else {
            nextIdx = clamp(0, _curLv - 2, this.map.children.length - 1);
            nextSp = this.map.children[nextIdx].getComponent(Sprite);
            nextSp && (nextSp.color = this.readyAtkColor);

            this.showMini();
        }
    }

    public hide(d?) {
        this.node.active = false;
        this.offEvents();
        this.resetEffects();
        this.resetBigAnim();
    };

    public update(dt) {
        this.updateEffects(dt);
        this.updateBigAnim(dt);
    }

    //#region --big-Map--
    //正常属性
    bigParam = {
        bigPos: v3(0, 0, 0),
        bigScale: v3(1, 1, 1),
        //
        mapPos: v3(0, 0, 0),
        mapScale: v3(1, 1, 1),
        //
        titlePos: v3(0, 330, 0),
        titleScale: v3(1, 1, 1),
    }
    isBigChangAnim = false;

    showBig(mapItem: Node, cb) {
        this.miniBg.active = false;
        this.bigBg.active = true;
        //
        this.bigBg.setPosition(this.bigParam.bigPos);
        this.bigBg.setScale(this.bigParam.bigScale);
        //
        this.map.setPosition(this.bigParam.mapPos);
        this.map.setScale(this.bigParam.mapScale);
        //
        this.title.setPosition(this.bigParam.titlePos);
        this.title.setScale(this.bigParam.titleScale);
        //        
        let img = mapItem.getComponent(Sprite).spriteFrame;
        this.showEffects(img, mapItem.position, () => {
            cb && cb();
            this.changeToMiniAnim();
        });
    }
    resetBigAnim() {
        Tween.stopAllByTarget(this.changeAnim.bigPos);
        Tween.stopAllByTarget(this.changeAnim.bigScale);
        Tween.stopAllByTarget(this.changeAnim.mapPos);
        Tween.stopAllByTarget(this.changeAnim.mapScale);
        Tween.stopAllByTarget(this.changeAnim.titlePos);
        Tween.stopAllByTarget(this.changeAnim.titleScale);
        this.isBigChangAnim = false;
    }

    //切换动画参数
    changeAnim = {
        bigPos: v3(),
        bigScale: v3(),
        //
        mapPos: v3(),
        mapScale: v3(),
        //
        titlePos: v3(),
        titleScale: v3(),
    }

    //切换动画-big -> min
    changeToMiniAnim() {
        this.changeAnim.bigPos.set(this.bigParam.bigPos);
        this.changeAnim.bigScale.set(this.bigParam.bigScale);
        this.changeAnim.mapPos.set(this.bigParam.mapPos);
        this.changeAnim.mapScale.set(this.bigParam.mapScale);
        this.changeAnim.titlePos.set(this.bigParam.titlePos);
        this.changeAnim.titleScale.set(this.bigParam.titleScale);

        this.isBigChangAnim = true;

        let t = 1;
        tween(this.changeAnim.bigPos).to(t, { x: this.miniParam.bigPos.x, y: this.miniParam.bigPos.y }, { easing: 'sineIn' }).start();
        tween(this.changeAnim.bigScale).to(t, { x: this.miniParam.bigScale.x, y: this.miniParam.bigScale.y }, { easing: 'sineIn' }).start();
        tween(this.changeAnim.mapPos).to(t, { x: this.miniParam.mapPos.x, y: this.miniParam.mapPos.y }, { easing: 'sineIn' }).start();
        tween(this.changeAnim.mapScale).to(t, { x: this.miniParam.mapScale.x, y: this.miniParam.mapScale.y }, { easing: 'sineIn' }).start();
        tween(this.changeAnim.titlePos).to(t, { x: this.miniParam.titlePos.x, y: this.miniParam.titlePos.y }, { easing: 'sineIn' }).start();
        tween(this.changeAnim.titleScale).to(t, { x: this.miniParam.titleScale.x, y: this.miniParam.titleScale.y }, { easing: 'sineIn' }).call(() => {
            this.showMini();
            this.isBigChangAnim = false;
        }).start();
        //
    }

    updateBigAnim(dt) {
        if (this.isBigChangAnim) {
            this.bigBg.setPosition(this.changeAnim.bigPos);
            this.bigBg.setScale(this.changeAnim.bigScale);
            //
            this.map.setPosition(this.changeAnim.mapPos);
            this.map.setScale(this.changeAnim.mapScale);
            //
            this.title.setPosition(this.changeAnim.titlePos);
            this.title.setScale(this.changeAnim.titleScale);
        }
    }

    //#endregion

    //#region --mini-Map--
    //缩小的属性
    miniParam = {
        bigPos: v3(0, 220, 0),
        bigScale: v3(0.6, 0.36, 0),
        //
        mapPos: v3(0, 220, 0),
        mapScale: v3(0.6, 0.6, 1),
        //
        titlePos: v3(0, 350, 0),
        titleScale: v3(0.6, 0.6, 0),
    }

    showMini() {
        this.miniBg.active = true;
        this.bigBg.active = false;
        //
        this.bigBg.setPosition(this.miniParam.bigPos);
        this.bigBg.setScale(this.miniParam.bigScale);
        //
        this.map.setPosition(this.miniParam.mapPos);
        this.map.setScale(this.miniParam.mapScale);
        //
        this.title.setPosition(this.miniParam.titlePos);
        this.title.setScale(this.miniParam.titleScale);

        this.mask.node.active = false;
    }

    //#endregion

    //#region --effects--
    effectRecs: { [uuid: string]: ZombieEffect } = {};
    isEffectFinish = false;
    finishCb = null;

    showEffects(img: SpriteFrame, toPos, cb) {
        this.resetEffects();
        //僵尸特效
        let num = 30;
        for (let i = 0; i < num; i++) {
            let e = GlobalPool.get('zombieEffect');
            e.parent = this.effectLayer;
            let cmp = new ZombieEffect(e, toPos, i);
            this.effectRecs[e.uuid] = cmp;
        }
        //mask
        this.showMaskAnim(img, toPos,);
        this.isEffectFinish = false;
        this.finishCb = cb;
    }

    resetEffects() {
        this.effectRecs = {};
        this.isEffectFinish = false;
        Tween.stopAllByTarget(this.maskScaleAnim);
        GlobalPool.putAllChildren(this.effectLayer);
    }

    maskScaleAnim = v3();
    //Mask动画
    showMaskAnim(img: SpriteFrame, toPos: Vec3,) {
        this.mask.node.active = true;
        let animNode = this.mask.node.children[0];

        this.mask.spriteFrame = img;
        this.mask.node.getComponent(UITransform).setContentSize(img.originalSize);
        this.mask.node.setPosition(toPos);
        //
        Tween.stopAllByTarget(this.maskScaleAnim);
        this.maskScaleAnim.set(0.1, 0.1, 1);
        animNode.setScale(this.maskScaleAnim);

        tween(this.maskScaleAnim).delay(1).to(6, { x: 10, y: 10 }, {
            easing: 'sineInOut', onUpdate: () => {
                animNode.setScale(this.maskScaleAnim);
            }
        }).call(() => {
            //隐藏mask
            this.mask.node.active = false;
        }).start();
    }

    updateEffects(dt) {
        if (!this.isEffectFinish) {

            for (const key in this.effectRecs) {
                const e = this.effectRecs[key];
                if (e.isFinish) {
                    GlobalPool.put(e.node);
                    delete this.effectRecs[key];
                } else {
                    e.update(dt);
                }
            }
            if (Object.keys(this.effectRecs).length == 0) {
                this.isEffectFinish = true;
                //隐藏mask
                this.mask.node.active = false;
                this.finishCb && this.finishCb();
                this.finishCb = null;
            }
        }
    }

    //#endregion
}

export class ZombieEffect {
    node: Node = null;
    pos = v3();
    scale = v3();
    toPos = v3();
    delay = 0;
    animTime = 0;
    isFinish = false;
    idx = 0;
    constructor(e: Node, toPos: Vec3, idx) {
        this.node = e;
        this.toPos.set(toPos);
        this.scale.set(0, 0, 0);
        this.idx = idx;
        // 随机位置-延迟
        this.isFinish = false;
        this.pos.x = 100 + Math.random() * 150;
        this.animTime = this.pos.x / 150;
        Vec3.rotateZ(this.pos, this.pos, Vec3.ZERO, Math.random() * 6.28);
        this.pos.add(this.toPos);
        //
        this.delay = 0.1 * idx;
        this.showAnim();
    }

    update(dt) {
        if (this.isFinish && this.node.active) return;
        this.node.setPosition(this.pos);
        this.node.setScale(this.scale);
    }

    showAnim() {
        this.node.active = false;
        let scaleInTime = 0.5;
        this.node.setPosition(this.pos);
        //位移
        tween(this.pos).
            delay(this.delay).
            call(() => {
                this.node.active = true;
                //缩放
                this.scale.set(0, 0, 0);
                tween(this.scale).
                    to(scaleInTime, { x: 1, y: 1 }, { easing: 'backOut' }).
                    delay(this.animTime - scaleInTime).
                    to(scaleInTime, { x: 0, y: 0 }, { easing: 'backIn' }).
                    start();
                //
            }).delay(scaleInTime).
            to(this.animTime, { x: this.toPos.x, y: this.toPos.y }).
            delay(scaleInTime).
            call(() => {
                this.isFinish = true;
            }).start();

    }
}